package com.gitee.core.ftp;

import com.jcraft.jsch.*;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Properties;

/**
 * 连接池工厂类
 * 
 * @author PYY
 * 
 */
public class ChannelSftpFactory implements PooledObjectFactory<ChannelSftp> {

    private static Logger logger = LoggerFactory.getLogger(ChannelSftp.class);

    /** FTP 登录用户名 */
    private String username;

    /** FTP 登录密码 */
    private String password;

    /** 私钥文件的路径 */
    private String keyFilePath;

    /** FTP 服务器地址IP地址 */
    private String host;

    /** FTP 端口 */
    private int port;

    public ChannelSftpFactory(String username, String password, String host, int port) {
        this.username = username;
        this.password = password;
        this.host = host;
        this.port = port;
    }

    @Override
    public PooledObject<ChannelSftp> makeObject() throws Exception {
        ChannelSftp ftpClient = null;
        try {
            JSch jsch = new JSch();
            if (keyFilePath != null) {
                jsch.addIdentity(keyFilePath);// 设置私钥
                logger.debug("sftp connect,path of private key file：" + keyFilePath);
            }

            Session session = jsch.getSession(username, host, port);
            logger.debug("sftp connect by host:" + host + " username:" + username);
            logger.debug("Session is build");
            if (password != null) {
                session.setPassword(password);
            }
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            config.put("PreferredAuthentications", "publickey,keyboard-interactive,password");
            session.setConfig(config);
            session.connect();
            logger.debug("Session is connected");

            Channel channel = session.openChannel("sftp");
            channel.connect();
            logger.debug("channel is connected");

            ftpClient = (ChannelSftp) channel;
            logger.debug(String.format("sftp server host:[%s] port:[%s] is connect successfull", host, port));
        } catch (JSchException e) {
            logger.error("Cannot connect to specified sftp server : " + host + port + ":{} \n Exception message is: "
                    + e.getMessage());
        }

        return new DefaultPooledObject<>(ftpClient);
    }

    @Override
    public void destroyObject(PooledObject<ChannelSftp> obj) throws Exception {
        ChannelSftp ftpClient = obj.getObject();
        try {
            if (ftpClient != null && ftpClient.isConnected()) {
                ftpClient.disconnect();
                ;
            }
        } catch (Exception e) {
            logger.error("ftp client logout failed...{}", e);
            throw e;
        } finally {
            if (ftpClient != null) {
                ftpClient.disconnect();
            }
        }

    }

    @Override
    public void activateObject(PooledObject<ChannelSftp> arg0) throws Exception {
        // TODO Auto-generated method stub

    }

    @Override
    public void passivateObject(PooledObject<ChannelSftp> arg0) throws Exception {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean validateObject(PooledObject<ChannelSftp> obj) {
        ChannelSftp ftpClient = obj.getObject();
        try {
            return ftpClient.isConnected();
        } catch (Exception e) {
            logger.error("Failed to validate client: {}", e);
        }
        return false;
    }

}
